package aspect.example;
import aspect.entity.behavior.Behavior;
import static aspect.core.AspectLauncher.*;
import static aspect.core.AspectRenderer.*;
import aspect.entity.Entity;
import aspect.entity.Player;
import aspect.event.KeyEvent;
import aspect.physics.Time;
import aspect.render.FrameBuffer;
import aspect.render.Light;
import aspect.render.Material;
import aspect.render.Mesh;
import aspect.render.ViewModel;
import aspect.render.shader.Shader;
import aspect.render.shader.ShaderProgram;
import static aspect.resources.Resources.*;
import aspect.util.Angles;
import aspect.util.Color;
import aspect.util.Vector2;
import static org.lwjgl.input.Keyboard.*;
import aspect.util.Vector3;
import aspect.world.ListWorld;
import aspect.world.World;
import java.io.File;
import java.util.Arrays;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
public class AspectTest extends Behavior {
private Entity terrain;
private Entity water;
private Player p;
private ViewModel crosshair;
private ViewModel skybox;
private World world;
private FrameBuffer fbo;
private ShaderProgram post;
private float[][] t;
private static final long seed = 2014;
public static final Random r = new Random(seed);
public static void main(String[] args) {
createAnimation(800, 600, false, 60, new AspectTest());
printFPS(1000);
}
@Override
public void onAdd() {
//setAmbientLight(new Color(0.2f, 0.2f, 0.2f));
setAmbientLight(Color.BLACK);
p = new Player(Vector3.zero());
p.setWalkSpeed(50);
Light l = new Light(Color.WHITE);
l.directional = true;
l.pos = new Vector3(0, 1, 0);
l.setAttenuation(1.0f, 0.0f, 0.0f);
crosshair = sprite(new Material(loadTexture(new File("materials/crosshair.png"))), 1, 1);
int pow = 8;
int w = (1 << pow);
t = new float[w][w];
///diamondSquare(t, w);
//NoiseTest.generateTerrain(t, w);
FFTTest.generateTerrain(t, w);
try {
fbo = new FrameBuffer(1024, 1024, p);
fbo.setRepeat(false);
fbo.setFilter(GL11.GL_NEAREST, GL11.GL_NEAREST);
Shader vert = Shader.loadPrebuilt("texture.vert", Shader.Type.VERTEX);
Shader frag = loadShader(new File("shaders/test.frag"), Shader.Type.FRAGMENT);
post = new ShaderProgram(vert, frag);
fbo.postProcess(post);
} catch (LWJGLException ex) {
Logger.getLogger(AspectTest.class.getName()).log(Level.SEVERE, null, ex);
}
terrain = new Entity(genMesh(t, new Material(loadTexture(new File("materials/rock.jpg"))), 32.0f, 0.25f));
//Material wat = new Material(new Color(0.0f, 0.1f, 0.6f, 0.7f));
Material wat = new Material(loadTexture(new File("materials/water.jpg")));
//wat.specular = Color.WHITE;
wat.shininess = 0.05f;
wat.shader = ShaderProgram.loadPrebuilt("water");
water = new Entity(rect(wat, 8.0f, 8.0f, w, w));
water.ang.pitch = -90;
water.pos = new Vector3(w / 2.0f, 0, w / 2.0f);
Material sky = new Material(loadTexture(new File("materials/stars.jpg")));
sky.shader = ShaderProgram.TEXTURE;
skybox = box(sky, 1.0f, 1.0f, 1.0f);
//makeFog(0.01f, Color.WHITE, 1);
world = new ListWorld();
for (int i = 0; i < 50; i++) {
int x;
int z;
do {
x = r.nextInt(w);
z = r.nextInt(w);
} while (t[x][z] < 0.0f);
Tree tree = new Tree();
tree.pos = new Vector3(x, t[x][z] + tree.height / 2, z);
world.add(tree);
}
}
private float getY(float x, float z) {
int i = (int)x;
int j = (int)z;
if (i < 0 || j < 0 || i >= t.length - 1 || j >= t.length - 1) {
return 0;
}
float dx = x - i;
float dz = z - j;
Vector3 point1 = new Vector3(i, t[i][j], j);
Vector3 point2 = new Vector3(i + 1, t[i + 1][j + 1], j + 1);
Vector3 point3;
if (dx > dz) {
point3 = new Vector3(i + 1, t[i + 1][j], j);
} else {
point3 = new Vector3(i, t[i][j + 1], j + 1);
}
Vector3 normal = normal(point1, point2, point3);
float a = normal.x;
float b = normal.y;
float c = normal.z;
float d = -(a * point1.x + b * point1.y + c * point1.z);
return -(a * x + c * z + d) / b;
}
private void diamondSquare(float[][] map, int w) {
map[0][0] = var(0, 0, w);
map[0][w] = var(0, w, w);
map[w][0] = var(w, 0, w);
map[w][w] = var(w, w, w);
while (w >= 2) {
step(map, w);
w /= 2;
}
}
private float var(int x, int z, int w) {
float v = 0.4f * w;
//Random r = new Random(((long)x) + (((long)z) << 32));
return (r.nextFloat() - 0.5f) * v;
//return 0;
}
private void step(float[][] map, int w) {
for (int i = 0; i < map.length - 1; i += w) {
for (int j = 0; j < map.length - 1; j += w) {
diamond(map, w, i, j);
square(map, w, i, j);
}
}
}
private void diamond(float[][] map, int w, int i, int j) {
int x = i + w / 2;
int y = j + w / 2;
float mean = (map[i][j] + map[i + w][j] + map[i][j + w] + map[i + w][j + w]) / 4.0f;
map[x][y] = mean + r.nextFloat() * var(x, y, w);
}
private void square(float[][] map, int w, int i, int j) {
int x = i + w / 2;
int y = j + w / 2;
squareMain(map, i, y, w / 2);
squareMain(map, x, j, w / 2);
squareMain(map, i + w, y, w / 2);
squareMain(map, x, j + w, w / 2);
}
private void squareMain(float[][] map, int x, int y, int w) {
int pts = 0;
float mean = 0.0f;
if (x - w > 0) {
mean += map[x - w][y];
pts++;
}
if (y - w > 0) {
mean += map[x][y - w];
pts++;
}
if (x + w < map.length) {
mean += map[x + w][y];
pts++;
}
if (y + w < map[0].length) {
mean += map[x][y + w];
pts++;
}
mean /= pts;
map[x][y] = mean + var(x, y, w * 2);
}
private ViewModel genMesh(float[][] heightmap, Material m, float texScale, float scale) {
m.cull = true;
float[] vertices = new float[(heightmap.length - 1) * (heightmap[0].length - 1) * 6 * 3];
float[] normals = new float[vertices.length];
float[] texcoords = new float[(heightmap.length - 1) * (heightmap[0].length - 1) * 6 * 2];
for (int i = 0; i < heightmap.length - 1; i++) {
for (int j = 0; j < heightmap[0].length - 1; j++) {
int index = (i * (heightmap.length - 1) + j) * 18;
int tindex = (i * (heightmap.length - 1) + j) * 12;
Vector3 v1 = new Vector3(i * scale, heightmap[i][j], j * scale);
Vector3 v2 = new Vector3(i * scale, heightmap[i][j + 1], (j + 1) * scale);
Vector3 v3 = new Vector3((i + 1) * scale, heightmap[i + 1][j + 1], (j + 1) * scale);
Vector3 v4 = new Vector3((i + 1) * scale, heightmap[i + 1][j], j * scale);
vertices[index + 0] = v1.x;
vertices[index + 1] = v1.y;
vertices[index + 2] = v1.z;
texcoords[tindex + 0] = v1.x / texScale;
texcoords[tindex + 1] = v1.z / texScale;
vertices[index + 3] = v2.x;
vertices[index + 4] = v2.y;
vertices[index + 5] = v2.z;
texcoords[tindex + 2] = v2.x / texScale;
texcoords[tindex + 3] = v2.z / texScale;
vertices[index + 6] = v3.x;
vertices[index + 7] = v3.y;
vertices[index + 8] = v3.z;
texcoords[tindex + 4] = v3.x / texScale;
texcoords[tindex + 5] = v3.z / texScale;
vertices[index + 9] = v3.x;
vertices[index + 10] = v3.y;
vertices[index + 11] = v3.z;
texcoords[tindex + 6] = v3.x / texScale;
texcoords[tindex + 7] = v3.z / texScale;
vertices[index + 12] = v4.x;
vertices[index + 13] = v4.y;
vertices[index + 14] = v4.z;
texcoords[tindex + 8] = v4.x / texScale;
texcoords[tindex + 9] = v4.z / texScale;
vertices[index + 15] = v1.x;
vertices[index + 16] = v1.y;
vertices[index + 17] = v1.z;
texcoords[tindex + 10] = v1.x / texScale;
texcoords[tindex + 11] = v1.z / texScale;
float[] n1 = faceNormals(v1, v2, v3);
System.arraycopy(n1, 0, normals, index, 9);
float[] n2 = faceNormals(v3, v4, v1);
System.arraycopy(n2, 0, normals, index + 9, 9);
}
}
return new Mesh(GeometryType.TRIANGLES, vertices, normals, texcoords, m);
}
@Override
public void update() {
p.update();
if (isKeyDown(KEY_LSHIFT)) {
p.pos.y -= 5.0f * Time.deltaTime();
}
if (isKeyDown(KEY_SPACE)) {
p.pos.y += 5.0f * Time.deltaTime();
}
if (p.pos.y < 0) {
post.setVar("water", true);
} else {
post.setVar("water", false);
}
p.pos.y = getY(p.pos.x, p.pos.z) + 10f;
}
@Override
public void render() {
fbo.capture();
Light.drawLights();
draw3D(skybox, p.pos, Angles.zero());
clearDepthBuffer();
terrain.render();
//world.draw();
//water.draw();
fbo.stop();
fbo.render();
draw2D(crosshair, new Vector2(Mouse.getX(), Mouse.getY()), 0);
}
}